﻿using DreamSpace.Net.ScriptEngines.V8;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using V8.Net;

namespace DreamSpace.Net.ScriptEngines
{
    // ========================================================================================================================

    /// <summary>
    /// Defines an expect interface for acting as a proxy to a script engine.
    /// This allows for various script engines (JScript, VBScript, V8, etc.) to easily be "plugged" into the server.
    /// </summary>
    public interface IScriptEngine : IDisposable
    {
        // --------------------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Registers the specified property name in the global scope and associates it with the given object instance.
        /// Returns true if successful.
        /// </summary>
        bool DefineGlobalProperty(string inScriptPropertyName, object objectInstance, ScriptMemberSecurity accessType = ScriptMemberSecurity.ReadWrite);

        /// <summary>
        /// Registers the specified type name in the global scope and associates it with the given C# type.
        /// Returns true if successful.
        /// </summary>
        bool DefineGlobalType(Type type, string inScriptTypeName, ScriptMemberSecurity accessType = ScriptMemberSecurity.ReadWrite);

        /// <summary>
        /// Registers the specified type name in the global scope and associates it with the given C# type.
        /// <para>This method is simply a convenient way to call the other overloaded method which expects a 'Type' argument.</para>
        /// Returns true if successful.
        /// </summary>
        bool DefineGlobalType<T>(string inScriptTypeName, ScriptMemberSecurity accessType = ScriptMemberSecurity.ReadWrite);

        /// <summary>
        /// Creates an object that will register in the scripting server as a shared "globals" property.
        /// The object must wrap and update the supplied global dictionary object (which is a reference to '{DreamSpaceServer}.Globals').
        /// The wrapper object must lock the global object before getting/setting the values as they become updated within the scripting environment.
        /// </summary>
        IBasicHandle CreateSharedGlobalObject(IDictionary<string, object> globalObject);

        /// <summary>
        /// Returns a reference to a call-back method to execute with a script is taking too long to execute.
        /// </summary>
        void SetTimeoutCallback(Action<IScriptEngine> callBack);

        /// <summary>
        /// Executes the given script code (see 'Evaluate()' for more details).
        /// 'sourceName' is simply a name (such as a file name, or other custom name) which identifies the script to be run (useful for debugging, etc.).
        /// </summary>
        /// <param name="script">The script to execute.</param>
        /// <param name="sourceName">The source of the script (such as a file name).</param>
        /// <param name="throwOnError">If true, any script errors should be thrown instead of returned.</param>
        IBasicHandle Execute(string script, string sourceName = null, bool throwOnError = false);

        /// <summary>
        /// Evaluates the script in context of an expression and returns the result.
        /// <para>How is this different from 'Execute()'? Well, in VBScript, the '=' symbol has two meanings: equality and assignment - so,
        /// which one to chose depends on the context. If this method is called, the context of "equality" would win.
        /// In JavaScript, however, this is not relevant.</para>
        /// </summary>
        /// <param name="script">The script to evaluate.</param>
        /// <param name="sourceName">The source of the script (such as a file name).</param>
        /// <param name="throwOnError">If true, any script errors should be thrown instead of returned.</param>
        IBasicHandle Evaluate(string script, string sourceName = null, bool throwOnError = false);

        /// <summary>
        /// Terminates any currently running script, which is useful if scripts are taking too long, or the host application is shutting down.
        /// </summary>
        void Interrupt();

        /// <summary>
        /// Loads a JavaScript file and executes it in the associated script environment.
        /// The result of the execution is returned.
        /// </summary>
        /// <param name="scriptFile">The filename (and optional path) to load.</param>
        /// <param name="sourceName">Something that describes the script being loaded (such as a file name).</param>
        /// <param name="throwExceptionOnError">If true, any error flags returned from the script will generate an error.</param>
        IBasicHandle LoadScript(string scriptFile, string sourceName = "DreamSpace Server", bool throwExceptionOnError = false);

        // --------------------------------------------------------------------------------------------------------------------
    }

    // ========================================================================================================================
}
